package com.esender.push.mq;

import com.esender.common.constant.RabbitMQConstants;
import com.esender.common.model.StandardReport;
import com.esender.common.util.JsonUtil;
import com.esender.push.config.RabbitMQConfig;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;

@Component
@Slf4j
public class PushReportListener {
    private int[] delayTimes = {0, 15000, 30000,60000,300000};
    private final String SUCCESS = "SUCCESS";
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RabbitListener(queues = RabbitMQConstants.SMS_PUSH_REPORT)
    public void consume(StandardReport standardReport, Channel channel, Message message) throws IOException {
        // 1、获取客户的回调地址
        //1、获取客户的回调地址
        String callbackUrl = standardReport.getCallbackUrl();
        if (StringUtils.isEmpty(callbackUrl)) {
            log.info("【推送模块-推送状态报告】 客户方没有设置回调的地址信息！callbackUrl = {} ", callbackUrl);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        //2、发送状态报告
        boolean flag = pushReport(standardReport);
        //3、如果发送失败，重试
        isResend(standardReport, flag);

        //4、直接手动ack
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    // 发送状态报告给callbackUrl
    boolean pushReport(StandardReport standardReport) {
        // 声明返回结果，你默认为false
        boolean flag = false;

        //1、声明发送的参数
        String body = JsonUtil.obj2JSON(standardReport);

        //2、声明RestTemplate的模板代码
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        try {
            log.info("【推送模块-推送状态报告】 第{}次推送状态报告开始！report = {}", standardReport.getResendCount() + 1,standardReport);
            String result = restTemplate.postForObject("http://" + standardReport.getCallbackUrl(), new HttpEntity<>(body, httpHeaders), String.class);
            flag = SUCCESS.equals(result);
        } catch (RestClientException e) {
            //e.printStackTrace();
        }
        //3、得到响应后，确认是否为SUCCESS
        return flag;
    }

    public void isResend(StandardReport standardReport,Boolean flag){
        if (!flag) {
            log.info("【推送模块-推送状态报告】 第{}次推送状态报告失败！report = {}",standardReport.getResendCount() + 1, standardReport);
            // TODO  重试~~
            standardReport.setResendCount(standardReport.getResendCount() + 1);
            if (standardReport.getResendCount() >= 5){
                return;
            }
            rabbitTemplate.convertAndSend(RabbitMQConfig.DELAYED_EXCHANGE, null, standardReport, new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    message.getMessageProperties().setDelay(delayTimes[standardReport.getResendCount()]);
                    return message;
                }
            });
        } else {
            log.info("【推送模块-推送状态报告】 第{}次推送状态报告成功！report = {}",standardReport.getResendCount(),standardReport);
        }
    }

    @RabbitListener(queues = RabbitMQConfig.DELAYED_QUEUE)
    public void delayedConsume(StandardReport standardReport,Channel channel,Message message) throws IOException {
        boolean flag = pushReport(standardReport);
        //3、如果发送失败，重试
        isResend(standardReport, flag);
        //4、直接手动ack
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}
